package com.bandi.tharshesnows;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.ToggleButton;

import com.bandi.tharshesnows.model.County;
import com.bandi.tharshesnows.model.Resort;
import com.bandi.tharshesnows.model.Skirun;
import com.bandi.tharshesnows.persistence.ApplicationPreferences;
import com.bandi.tharshesnows.persistence.DBUtils;
import com.bandi.tharshesnows.pics.PictureStorage;

@SuppressLint("NewApi")
public class MainActivity extends BaseActivity {

	private static final String TAG = "SNOW";
	private boolean importDB = false;
	private ListView listView;
	private List<County> counties = new ArrayList<County>();
	private LayoutInflater inflater;
	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
			"dd.MM.yyyy, HH:mm");
	private ProgressDialog progressDialog;
	private SkirunsProvider provider;
	private TextView openCountiesText;
	private boolean isDataLoaded = false;
	private CountiesAdapter countiesAdapter = new CountiesAdapter();
	private SkirunsAdapter skirunsAdapter = new SkirunsAdapter();
	private RelativeLayout menuLayout;
	private List<Skirun> allSkiruns = new ArrayList<Skirun>();
	private TextView listHint;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listView = (ListView) findViewById(R.id.counties_list);
		openCountiesText = (TextView) findViewById(R.id.open_counties_text);
		listView.setDivider(null);
		listView.setDividerHeight(0);
		inflater = LayoutInflater.from(this);
		provider = SkirunsProvider.getInstance();
		listView.setAdapter(countiesAdapter);
		listHint = (TextView) findViewById(R.id.name_highlight);
		listView.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				if (view.getAdapter() == skirunsAdapter) {
					switch (scrollState) {
					case OnScrollListener.SCROLL_STATE_IDLE:
						listHint.setVisibility(View.INVISIBLE);
						break;
					default:
						listHint.setVisibility(View.VISIBLE);
					}
				}
			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				if (view.getAdapter() == skirunsAdapter) {
					listHint.setText(allSkiruns.get(firstVisibleItem).getName()
							.substring(0, 1));
				}
			}
		});
		ImageButton menu = (ImageButton) findViewById(R.id.menu_btn);
		menuLayout = (RelativeLayout) findViewById(R.id.menu_layout);
		menu.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				int visibility = menuLayout.getVisibility();
				menuLayout.setVisibility(visibility == View.VISIBLE ? View.GONE
						: View.VISIBLE);
			}
		});
		ImageButton refresh = (ImageButton) findViewById(R.id.menu_refresh_btn);
		refresh.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				menuLayout.setVisibility(View.GONE);
				updateData();
			}
		});
		ImageButton search = (ImageButton) findViewById(R.id.menu_search_btn);
		ImageButton settings = (ImageButton) findViewById(R.id.menu_settings_btn);
		ToggleButton toggleLists = (ToggleButton) findViewById(R.id.toggle_list_btn);
		toggleLists.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				if (isChecked) {
					listView.setAdapter(skirunsAdapter);
					// listView.setFastScrollAlwaysVisible(true);
					listView.setFastScrollEnabled(true);
				} else {
					listView.setAdapter(countiesAdapter);
					listView.setFastScrollEnabled(false);
				}
			}
		});
	}

	private void dismissProgress() {
		if (progressDialog != null) {
			progressDialog.dismiss();
			progressDialog = null;
		}
	}

	private void updateData() {
		if (!isOnline()) {
			runOnUiThread(new Runnable() {

				@Override
				public void run() {
					dismissProgress();
					showFailedAlert("Nu exista o conexiune la internet!");
				}
			});
			return;
		}
		if (progressDialog == null) {
			progressDialog = ProgressDialog.show(this, "Actualizare",
					"Actualizare partii...");
		}
		provider.getCounties(true, new GetDataCallback<List<County>>() {

			@Override
			public void onError(Throwable t) {
				Log.e(TAG, "Failed to download data.", t);
				showFailedAlert("Actualizarea a esuat.");
				dismissProgress();
			}

			@Override
			public void onData(final List<County> data) {
				runOnUiThread(new Runnable() {

					@Override
					public void run() {
						counties = data;
						refreshList();
						dismissProgress();
					}
				});
			}
		});
	}

	private class SkirunsAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			return allSkiruns.size();
		}

		@Override
		public Object getItem(int position) {
			return allSkiruns.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = inflater.inflate(R.layout.skirun_item_layout,
						null);
				convertView.setTag(new SkirunViewWrapper(convertView));
			}
			SkirunViewWrapper wrapper = (SkirunViewWrapper) convertView
					.getTag();
			wrapper.refresh(allSkiruns.get(position));
			return convertView;
		}

	}

	private class SkirunViewWrapper {
		TextView skirunName;
		ImageView skirunStatus;
		ImageView skirunSaved;
		View parent;

		public SkirunViewWrapper(View convertView) {
			this.parent = convertView;
			skirunName = (TextView) convertView.findViewById(R.id.skirun_name);
			skirunStatus = (ImageView) convertView
					.findViewById(R.id.skirun_open_img);
			skirunSaved = (ImageView) convertView
					.findViewById(R.id.skirun_stored_img);
		}

		public void refresh(final Skirun skirun) {
			skirunSaved.setVisibility(skirun.isDownloaded() ? View.VISIBLE
					: View.GONE);
			skirunStatus
					.setBackgroundResource(skirun.isOpen() ? R.drawable.skirun_open_list_item
							: R.drawable.skirun_closed_list_item);
			skirunName.setText(skirun.getName());
			parent.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					if (!isOnline() && !skirun.isDownloaded()) {
						showFailedAlert("Nu exista o conexiune la internet!");
						return;
					}
					Intent intent = new Intent(MainActivity.this,
							SkirunActivity.class);
					intent.putExtra("SKIRUN_ID", skirun.get_id());
					intent.putExtra("LOC_ID", skirun.getResort().get_id());
					intent.putExtra("COUNTY_ID", skirun.getResort()
							.getCounty().get_id());
					startActivity(intent);
				}
			});
		}

	}

	private class CountiesAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			return counties.size();
		}

		@Override
		public Object getItem(int arg0) {
			return counties.get(arg0);
		}

		@Override
		public long getItemId(int arg0) {
			return arg0;
		}

		@Override
		public View getView(int position, View contentView, ViewGroup parent) {
			if (contentView == null) {
				contentView = inflater.inflate(R.layout.county_layout, null);
				CountyViewWrapper wrapper = new CountyViewWrapper(contentView);
				contentView.setTag(wrapper);
			}
			CountyViewWrapper wrapper = (CountyViewWrapper) contentView
					.getTag();
			wrapper.refresh(position);
			return contentView;
		}

	}

	private class CountyViewWrapper {
		TextView countyName;
		TextView skirunNr;
		TextView openSkirunNr;
		TextView localityNr;
		ImageView countyOpenImg;
		TextView lastUpdateText;
		View contentView;
		ImageView mapImg;

		public CountyViewWrapper(View contentView) {
			this.contentView = contentView;
			countyName = (TextView) contentView.findViewById(R.id.county_name);
			skirunNr = (TextView) contentView
					.findViewById(R.id.skiruns_total_nr_text);
			openSkirunNr = (TextView) contentView
					.findViewById(R.id.skiruns_open_nr_text);
			localityNr = (TextView) contentView.findViewById(R.id.localities);
			lastUpdateText = (TextView) contentView
					.findViewById(R.id.updateDateText);
			countyOpenImg = (ImageView) contentView
					.findViewById(R.id.county_open_img);
			mapImg = (ImageView) contentView.findViewById(R.id.county_map);
		}

		public void refresh(int position) {
			final County county = counties.get(position);
			countyName.setText(county.getName());
			localityNr.setText(MessageFormat.format(
					getString(R.string.localitati_txt), county.getResorts()
							.size()));
			int skiruns = 0;
			int openSkiruns = 0;
			Date lastUpdate = null;
			for (Resort locality : county.getResorts()) {
				Date localityLastUpdate = locality.getUpdated();
				if (localityLastUpdate != null) {
					if (lastUpdate == null) {
						lastUpdate = localityLastUpdate;
					} else {
						if (localityLastUpdate.getTime() > lastUpdate.getTime()) {
							lastUpdate = localityLastUpdate;
						}
					}
				}
				for (Skirun skirun : locality.getSkiruns()) {
					skiruns++;
					if (skirun.isOpen()) {
						openSkiruns++;
					}
				}
			}
			if (lastUpdate == null) {
				lastUpdateText.setVisibility(View.INVISIBLE);
			} else {
				lastUpdateText.setVisibility(View.VISIBLE);
				lastUpdateText.setText(MessageFormat.format(
						getString(R.string.last_update_txt),
						DATE_FORMAT.format(lastUpdate)));
			}
			skirunNr.setText("" + skiruns);
			if (county.getLocation() != null
					&& county.getLocation().getStaticMapImagePath() != null) {
				Bitmap bmp = PictureStorage.getInstance().getImage(
						county.getLocation().getStaticMapImagePath());
				if (bmp != null) {
					mapImg.setImageBitmap(bmp);
					mapImg.setVisibility(View.VISIBLE);
				} else if (isOnline()) {
					// TODO - download map
				}
			}
			openSkirunNr.setText("" + openSkiruns);
			if (openSkiruns > 0) {
				countyOpenImg
						.setBackgroundResource(R.drawable.skirun_open_list_item);
			} else {
				countyOpenImg
						.setBackgroundResource(R.drawable.skirun_closed_list_item);
			}
			contentView.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					Intent intent = new Intent(MainActivity.this,
							LocalitiesActivity.class);
					intent.putExtra("CountyID", county.get_id());
					startActivity(intent);
				}
			});
		}
	}

	@SuppressLint("NewApi")
	@Override
	protected void onResume() {
		super.onResume();
		if (importDB && ApplicationPreferences.getPreferences().isFirstStart()) {
			// copy db from assets
			progressDialog = ProgressDialog.show(this, "Actualizare",
					"Incarcare..");
			AsyncTask<Void, Void, Void> importTask = new AsyncTask<Void, Void, Void>() {

				@Override
				protected Void doInBackground(Void... params) {
					DBUtils dbUtils = new DBUtils();
					dbUtils.importDBFromAssets(MainActivity.this);
					return null;
				}
				
				@Override
				protected void onPostExecute(Void result) {
					progressDialog.dismiss();
					loadDataFromDB();
					ApplicationPreferences.getPreferences().setFirstStart(false);
				}

			};
			if (Build.VERSION.SDK_INT >= 11) {
				importTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
			} else {
				importTask.execute();
			}
			return;
		}
		loadDataFromDB();
	}
	
	private void loadDataFromDB(){
		if (!isDataLoaded) {
			progressDialog = ProgressDialog.show(this, "Actualizare",
					"Actualizare partii...");
			provider.getCounties(false, new GetDataCallback<List<County>>() {

				@Override
				public void onError(Throwable t) {
					Log.e(TAG, "Failed to download data.", t);
					showFailedAlert("Actualizarea a esuat.");
					dismissProgress();
				}

				@Override
				public void onData(final List<County> data) {
					if (data == null || data.size() < 1) {
						updateData();
					} else {
						runOnUiThread(new Runnable() {

							@Override
							public void run() {
								counties = data;
								refreshList();
								dismissProgress();
							}
						});

					}
				}
			});
		} else {
			refreshList();
		}
	}

	private void refreshList() {
		int openCounties = 0;
		allSkiruns.clear();
		County openCounty = null;
		for (County c : counties) {
			boolean foundSkirun = false;
			for (Resort l : c.getResorts()) {
				for (Skirun s : l.getSkiruns()) {
					allSkiruns.add(s);
					if (s.isOpen()) {
						foundSkirun = true;
					}
				}
			}
			if (foundSkirun) {
				openCounties++;
				if (openCounty == null) {
					openCounty = c;
				}
			}
		}
		switch (openCounties) {
		case 0:
			openCountiesText.setText(R.string.skiing_closed);
			break;
		case 1:
			openCountiesText.setText(MessageFormat.format(
					getString(R.string.skiing_open_in_one_county),
					openCounty.getName()));
			break;
		default:
			openCountiesText.setText(MessageFormat.format(
					getString(R.string.skiing_open), openCounties));
		}
		Collections.sort(allSkiruns, new Comparator<Skirun>() {

			@Override
			public int compare(Skirun lhs, Skirun rhs) {
				return lhs.getName().compareTo(rhs.getName());
			}
		});
		countiesAdapter.notifyDataSetChanged();
		skirunsAdapter.notifyDataSetChanged();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuItem menuItem = menu.add("Refresh");
		menuItem.setIcon(R.drawable.ic_menu_refresh);
		// menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
		menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {

			@Override
			public boolean onMenuItemClick(MenuItem item) {
				updateData();
				return true;
			}
		});
		MenuItem exportDbItem = menu.add("Export DB");
		exportDbItem.setIcon(R.drawable.ic_menu_save);
		exportDbItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {

			@Override
			public boolean onMenuItemClick(MenuItem item) {
				Thread t = new Thread() {
					@Override
					public void run() {
						Log.d("DB", "starting db export");
						DBUtils dbUtils = new DBUtils();
						dbUtils.exportToExternalStorage(MainActivity.this);
						Log.d("DB", "db export finished");
					}
				};
				t.start();
				return true;
			}
		});
		return true;
	}

}
